
package com.solution.wx.core.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.HttpException;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSONObject;
import com.solution.admin.auth.entity.UserEntity;
import com.solution.admin.auth.security.UsernamePasswordToken;
import com.solution.admin.auth.service.UserService;
import com.solution.admin.home.service.RedisService;
import com.solution.admin.settings.entity.KeyMapEntity;
import com.solution.admin.settings.service.KeyMapService;
import com.solution.common.config.PublicConfigUtil;
import com.solution.common.constants.PublicStatus;
import com.solution.common.constants.PublicStatus.USER_APPROVE_STATUS;
import com.solution.common.constants.PublicStatus.USER_TYPE;
import com.solution.common.controller.BaseController;
import com.solution.common.exception.WebException;
import com.solution.common.utils.rsa.SHA1;
import com.solution.common.utils.string.StringUtil;
import com.solution.wx.core.constants.WechatConstants;
import com.solution.wx.core.entity.SNSUserEntity;
import com.solution.wx.core.service.WechatService;
import com.solution.wx.core.util.WechatUtil;

/**
 * 微信控制层
 * @author: solin
 * @date: 2017年11月12日 上午09:00:07
 */
@RequestMapping("/wx")
@Controller("wechatController")
public class WechatController extends BaseController{
	Logger logger = Logger.getLogger(WechatController.class);
	
	@Autowired
	WechatService wechatService;
	
	@Autowired
    RedisService redisService;
	
	@Autowired
	UserService userService;
	
	/**
	 * 字典查询service组件
	 */
	@Autowired
	private KeyMapService keyMapService;
	
	
	/**
	 * OAuth2.0网页授权
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 * @author: solin
	 * @date: 2017年11月12日 上午12:57:19
	 */
	@RequestMapping("/auth")
	public String wechatAuth(HttpServletRequest request,HttpServletResponse response) throws Exception {
		String state = request.getScheme() + "://" + request.getServerName()
				+ request.getContextPath();
		// 回调地址  /wx/authSuccess
		String redirect_uri = PublicConfigUtil.readConfig("auth_redirect");
		// 判断是否有请求参数 (WechatConstants.SRC_PAGE_URL_KEY = gotoUrl)
		String requestParam = request.getQueryString();
		if (StringUtil.isNotEmpty(requestParam)) {
			redirect_uri = (redirect_uri + "?").concat(requestParam);
		}
		// 需要对回调地址进行编码
		String encode_redirect_uri = URLEncoder.encode(redirect_uri, "UTF-8");
		// 拼接微信认证地址
		String authorizeUrl = WechatUtil.AUTHORIZE_URL
				.replace("APPID", WechatUtil.APPID)
				.replace("ENCODE_REDIRECT_URI", encode_redirect_uri)
				.replace("SCOPE", WechatUtil.SCOPE_SNSPAIUSERINFO)
				.replace("STATE", state);
		return "redirect:" + authorizeUrl;
	}
	
	
	/**
	 * 从请求QueryString 中获取跳转的地址
	 * @param requestParam
	 * @return
	 */
	private String getGotoUrlFromQueryString(String requestParam){
		String goToUrl = null;
		String[] requestParamPairArr = requestParam.split("&");
		for(String paramPair : requestParamPairArr){
			String[] params = paramPair.split("=");
			if(params[0].equals(WechatConstants.SRC_PAGE_URL_KEY)){
		 		goToUrl = params[1];
				try {
					goToUrl = URLDecoder.decode(goToUrl, "UTF-8");
				} catch (UnsupportedEncodingException e) {
					logger.error("微信公众号菜单跳转地址解码失败", e);
				}
			}
		}
		return goToUrl;
	}
	
	
	/**
	 * OAuth2.0网页授权成功
	 * @param request
	 * @param response
	 * @return
	 * @author: solin
	 * @date: 2017年11月14日 上午12:58:56
	 */
	@RequestMapping("/authSuccess")
	public String wechatAuthSuccess(HttpServletRequest request,HttpServletResponse response){
		// 跳转的Url
		String goToUrl = request.getParameter("goToUrl");
		// 认证后要跳转的页面
		String openId = WechatUtil.getOpenIdFromCookie(request);
		if(StringUtil.isEmpty(openId)){
			// 微信授权返回的code码
			String code = request.getParameter("code");
			if(null != code){	
				// 根据code获取授权接口的AccessToken 
				JSONObject tokenResult = WechatUtil.getAccessTokenForCode(code);
				//若是openId不为空则获取对应的用户信息
				openId = tokenResult.getString("openid");
				String accessToken = tokenResult.getString("access_token");
				if(null != openId){
					//创建cookie  //Cookie的有效期设置为一年
					Cookie openIdCookie = new Cookie("openId",openId);
					openIdCookie.setMaxAge(12*30*24*60*60);
					openIdCookie.setPath("/");
					response.addCookie(openIdCookie);
					
					//将通过网页授权获取用户信息保存到redis中
					SNSUserEntity snsUserInfo = null;
					try {
						snsUserInfo = WechatUtil.getSNSUserInfo(accessToken, openId);
					} catch (Exception e) {
						logger.error("通过微信公众号网页授权获取大用户信息失败",e);
					}
					if(snsUserInfo != null){
						redisService.del(WechatConstants.SNS_USERINFO_KEY.concat(openId));
						redisService.saveSys(WechatConstants.SNS_USERINFO_KEY.concat(openId), JSONObject.toJSONString(snsUserInfo));
					}
				}
			}
		}
		
		//获取网页授权用户信息
		try {
			//shiro登录，这个步骤有可能登录失败的，如果open还没有绑定用户怎么处理？
			Integer homeType = wechatLogin(openId);
			if(homeType == -1){
				// 登录未找到用户,跳转绑定页面,此时cookie 中应该已经有openid了
				return "wx/my/bindAccount";
			}
			
			//根绝角色判断，如果是商户人员，则跳到商户端首页
			if (1 == homeType) {
				return "redirect:/wx/index";
			}
			
			// 如果是跳转绑定页面的，就直接进入绑定页面，不要跳转
			if("/wx/my/toBindAccountPage".equals(goToUrl)){
				return "wx/my/bindAccount";
			}
			//如果检测到有原页面请求地址，则再跳转到请求验证之前的页面
			if (StringUtil.isNotEmpty(goToUrl)) {
				return "redirect:/".concat(goToUrl);
			}
			return "redirect:/wx/index";
		} catch (Exception e) {
			logger.error("微信授权获取用户接口调用异常", e);
			throw new WebException(e.getLocalizedMessage());
		}
	}
	
	/**
	 * 微信端登录
	 * @param openId
	 * @author: solin
	 * @date: 2017年11月16日 下午2:25:15
	 * @return 返回跳转类型 0 客户首页  1 商户首页 -1 登录失败
	 */
	private Integer wechatLogin(String openId) {
		Integer homeType = 0;
		//通过openid到数据库中查询判断用户是否存在
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("openId", StringUtil.isEmpty(openId) ? null : openId);
		List<UserEntity> userList = userService.getUserList(param);
		if(userList != null && userList.size() > 0){
			UserEntity user = userList.get(0);
			//shiro登录
			Subject currentUser = SecurityUtils.getSubject();
			UsernamePasswordToken token = new UsernamePasswordToken();
			token.setUsername(userList.get(0).getUserCode());
			token.setPassword(userList.get(0).getPassword().toCharArray());
			token.setLoginTerminal(PublicStatus.LOGIN_TERMINAL_TYPE.WX.getCode());
			currentUser.login(token);
			// 如果是客户，homeType 返回1
			if (!USER_TYPE.CUSTOMER.getId().equals(userList.get(0).getUserType())) {
				homeType = 1;
			}
		}else{
			// 用户不存在
			homeType = -1;
		}
		return homeType;
	}

	/**
	 * 微信公众号自定义token验证
	 * @param response
	 * @param request
	 * @throws IOException
	 * @author: solin
	 * @date: 2017年11月12日 上午12:49:12
	 */
	@RequestMapping("/authToken")
	public void wechatCallbackApi(HttpServletResponse response,
			HttpServletRequest request) throws IOException {

		response.setCharacterEncoding("UTF-8");
		request.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();

		String signature = request.getParameter("signature");// SHA1加密字符串
		String timestamp = request.getParameter("timestamp");// 时间
		String nonce = request.getParameter("nonce");// 随机数

		String echoStr = request.getParameter("echostr");// 随机字符串

		System.out.println("echoStr=======" + echoStr); 

		if (StringUtil.isNotNull(echoStr)) {
			String[] b = { WechatUtil.TOKEN, timestamp, nonce };
			Arrays.sort(b);
			String strB = "";
			for (int j = 0; j < b.length; j++) {
				strB += b[j];
			}

			String echoB = new SHA1().getDigestOfString(strB.getBytes());
			System.out.println("echoB======" + echoB);
			System.out.println("signature======" + signature);
			if (echoB.equals(signature)) {
				out.print(echoStr);
			} else {
				out.print("");
			}
		}else{
			try {
				//System.out.println("request======" + request);
				String getXml = this.wechatService.pushManage(request);
				System.out.println("getXml:" + getXml);
				out.print(getXml);
			} catch (Exception e) {
				e.printStackTrace();
				out.print("");
			}
		}
		out.flush();
		out.close();
	}

}
